#include "StdAfx.h"
#include "FindFileSorted.h"

void CFindFileSorted::ToUpper(TCHAR *s1)
{
   TCHAR *s2 = (TCHAR *) s1;

   while (*s2)
   {
      *s2 = _totupper(*s2);
      s2++;
   }
}

CFindFileSorted::CFindFileSorted(TCHAR *szDirectory, TCHAR *szPattern)
{
   iCount = 0;

   szList = szListUpper = NULL;

   TCHAR szAuxiliary[MAX_PATH];
   StringCchCopy(szAuxiliary, sizeof(szAuxiliary), szDirectory);
   StringCchCat(szAuxiliary, sizeof(szAuxiliary), szPattern);

   ListDirectory(szAuxiliary);

   if (iCount > 0)
      OrderListByName();
}

CFindFileSorted::~CFindFileSorted(void)
{
   if (szList != NULL)
   {
      for (int i = 0; i < iCount; i++)
         VirtualFree(szList[i], 0, MEM_RELEASE);

      VirtualFree(szList, 0, MEM_RELEASE);
   }

   if (szListUpper != NULL)
   {
      for (int i = 0; i < iCount; i++)
         VirtualFree(szListUpper[i], 0, MEM_RELEASE);

      VirtualFree(szListUpper, 0, MEM_RELEASE);
   }
}

void CFindFileSorted::ListDirectory(TCHAR *szWhatToFind)
{
	WIN32_FIND_DATA findFileData;
	HANDLE handle;
	BOOL found = false;

   // Discover how many files whe have
   iCount = 0;

	handle = FindFirstFile(szWhatToFind, &findFileData);

	if (handle != INVALID_HANDLE_VALUE)
   {
		do
      {
			iCount++;

			found = FindNextFile(handle, &findFileData);
		} while (found);

      iCount++;

		FindClose(handle);
	}

   if (iCount <= 0)
      return;

   // Allocate memory for hour array
   szList = (TCHAR **) VirtualAlloc(NULL, iCount * sizeof(TCHAR *), MEM_COMMIT, PAGE_READWRITE);
   szListUpper = (TCHAR **) VirtualAlloc(NULL, iCount * sizeof(TCHAR *), MEM_COMMIT, PAGE_READWRITE);

   // Discover how many files whe have
   iCount = 0;

	handle = FindFirstFile(szWhatToFind, &findFileData);

	if (handle != INVALID_HANDLE_VALUE)
   {
		do
      {
         szList[iCount] = (TCHAR *) VirtualAlloc(NULL, (_tcslen(findFileData.cFileName) + 1) * sizeof(TCHAR), MEM_COMMIT, PAGE_READWRITE);
         StringCchCopy(szList[iCount], MAX_PATH, findFileData.cFileName);

         szListUpper[iCount] = (TCHAR *) VirtualAlloc(NULL, (_tcslen(findFileData.cFileName) + 1) * sizeof(TCHAR), MEM_COMMIT, PAGE_READWRITE);
         StringCchCopy(szListUpper[iCount], MAX_PATH, findFileData.cFileName);

         ToUpper(szListUpper[iCount]);

         iCount++;

         found = FindNextFile(handle, &findFileData);
		} while (found);

		FindClose(handle);
	}
}

void CFindFileSorted::OrderListByName()
{
   // Using shell sort
   int h, size = iCount;
   TCHAR szAuxiliary[MAX_PATH], szAuxiliaryUpper[MAX_PATH];

   for(h = 1; h < size; h = 3 * h + 1);

   do
   {
      h /= 3;

      for (int i = h; i < size; ++i)
      {
         StringCchCopy(szAuxiliary, MAX_PATH, szList[i]);
         StringCchCopy(szAuxiliaryUpper, MAX_PATH, szListUpper[i]);

         int j;

         for(j = i - h; ((j >= 0) && ((_tcscmp(szListUpper[j], szAuxiliaryUpper) > 0))); j -= h)
         {
            StringCchCopy(szList[j + h], MAX_PATH, szList[j]);
            StringCchCopy(szListUpper[j + h], MAX_PATH, szListUpper[j]);
         }

         StringCchCopy(szList[j + h], MAX_PATH, szAuxiliary);
         StringCchCopy(szListUpper[j + h], MAX_PATH, szAuxiliaryUpper);
      }
   } while( h > 1 );
}

TCHAR *CFindFileSorted::getAt(int iPosition)
{
   return szList[iPosition];
}

int CFindFileSorted::getCount()
{
   return iCount;
}